#ifndef __xwt_graphics_h
  #define __xwt_graphics_h

#include <xwt/xwt_defs.h>
#include <sysport/sysport.h>

XWT_BEGIN_NAMESPACE(xwt);

struct Rect {
	int left, top;
	int width, height;
	Rect () {}
	Rect (int _x, int _y, int _cx, int _cy) : 
	left(_x), top(_y), width(_cx), height(_cy) { }
};

struct Point {
	int x, y;
	Point () {}
	Point (int _x, int _y) : x(_x), y(_y) { }
};

struct Size {
	int cx, cy;
	Size () {}
	Size (int _cx, int _cy) : cx(_cx), cy(_cy) { }
};

struct Color {
	int r, g, b;
	Color () { }
	Color (int _r, int _g, int _b) : r(_r), g(_g), b(_b) { }
};

// MemoryBitmap...
class MemoryBitmap {
protected:
	HBITMAP m_hBitmap;
	HGDIOBJ m_hOldBitmap;
	HDC m_hDC;
public:
	MemoryBitmap () {
		m_hBitmap = NULL;
		m_hOldBitmap = NULL;
		m_hDC = NULL;
	}
	~MemoryBitmap () {
		Dispose ();
	}
	HDC GetDC () const {
		return m_hDC;
	}
	bool Create (int cx, int cy, HDC hRefDC = NULL);
	void Dispose ();
};

// Font
class Font {
protected:
#ifdef WIN32
	HFONT m_hFont;
#endif

public:
	Font () {
	#ifdef WIN32
		m_hFont = NULL;
	#endif
	}
	Font (const sys_tchar *face_name, int size, HDC hdc) {
		m_hFont = NULL;
		Create (face_name, size, hdc, FW_NORMAL);
	}
	Font (const Font &fnt) {
		m_hFont = NULL;
	}
	~Font () {
		Delete ();
	}
	operator HFONT () {
		return m_hFont;
	}
	
	bool Create (const sys_tchar *face_name, int size, HDC hdc, long weight);

	bool Create (const sys_tchar *face_name, int size, HDC hdc) {
		return Create (face_name, size, hdc, FW_NORMAL);
	}
	
	bool Create (const sys_tchar *face_name, int size) {
		HDC hdc = CreateCompatibleDC (NULL);
		bool ret = Create (face_name, size, hdc, FW_NORMAL);
		::DeleteDC (hdc);
		return ret;
	}

	void Delete () {
		if (m_hFont) {
			DeleteObject (m_hFont);
			m_hFont = NULL;
		}
	}
};

// GC
class GC {
public:
	// HDC handle types
	enum HDCType {
		hdcTypeInvalid = -1,
		hdcTypeWindow,
		hdcTypePaint
	};

#ifdef WIN32
	HWND m_hWnd;
	HDC m_hdc;
	PAINTSTRUCT m_ps;
	HDCType m_hdc_type;
	int m_dc_context;
	bool m_flag_erase_bkgnd;
#endif	

private:
	GC &operator= (const GC &gc) { 
		// no assignment 
	}	

	// dispose the HDC handle
	void Dispose ();

public:
	GC ();

	virtual ~GC () {
		Dispose ();
	}

public:
#ifdef WIN32
	HDC Win32GetHDC () const {
		return m_hdc; 
	}
#endif
	bool ShouldEraseBackground () const {
		return m_flag_erase_bkgnd;
	}
	void UpdateEraseBackgroundFlag (bool flag) {
		m_flag_erase_bkgnd = flag;
	}

	// drawing operations...
public:
	void SetFillColor (const Color &color);
	void SetPenColor (const Color &color);
	void Rectangle (int x, int y, int cx, int cy);

	// static factory methods...
public:
#ifdef WIN32
	static GC *CreateWindowGC (HWND hwnd);
	static GC *CreatePaintGC (HWND hwnd);
#endif
};

// conversion macros...
#ifdef WIN32
inline RECT ToWin32Rect (const Rect &rt) {
	RECT rect = { rt.left, rt.top, rt.left + rt.width - 1, rt.top + rt.height - 1 };
	return rect;
}

inline POINT ToWin32Point (const Point &pt) {
	POINT point = { pt.x, pt.y };
	return point;
}

inline SIZE ToWin32Size (const Size &size) {
	SIZE cx = { size.cx, size.cy };
	return cx;
}

inline COLORREF ToWin32Color (const Color &clr) {
	return RGB(clr.r, clr.g, clr.b);
}

inline Rect ToXWTRect (const RECT &rt) {
	Rect rect (rt.left, rt.top, rt.right - rt.left + 1, rt.bottom - rt.top + 1);
	return rect;
}

inline Point ToXWTPoint (const POINT &pt) {
	Point point (pt.x, pt.y);
	return point;
}

inline Size ToXWTSize (const SIZE &sizep) {
	Size size (sizep.cx, sizep.cy);
	return size;
}

inline Color ToXWTColor (const COLORREF &clr) {
	Color color;
	color.r = GetRValue(clr);
	color.g = GetGValue(clr);
	color.b = GetBValue(clr);
	return color;
}
#endif /* WIN32 */

XWT_END_NAMESPACE(xwt);

#endif /* __xwt_graphics_h */
